package com.mezz.bones.im.common.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mezz.bones.im.common.domain.dto.ApplicationDto;
import com.mezz.bones.im.common.domain.request.UserSignRequest;
import com.mezz.bones.im.common.exception.ImBaseException;
import com.mezz.bones.im.common.domain.user.ImUserAuthInfo;
import com.mezz.bones.im.common.result.ImResultCode;
import com.mezz.bones.im.common.service.IApplicationService;
import com.mezz.bones.im.common.service.IAuthService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: zhuang
 * @Date: 2024/12/5 17:14
 * @Description: 用户认证服务实现类
 * @Version: 1.0
 **/

@Service
@AllArgsConstructor
public class AuthServiceImpl implements IAuthService {

    private final IApplicationService applicationService;
    /**
     * 生成JWT Token
     * @param request 用户签名请求
     * @return JWT Token字符串
     */
    public String generateToken(UserSignRequest request) {


        Date now = new Date();
        Map<String, Object> claims = new HashMap<>();
        claims.put("appId", request.getAppId());
        claims.put("userId", request.getUserId());
        claims.put("userType", request.getUserType());
        
        // 使用应用的appSecret作为密钥
        byte[] keyBytes = request.getAppSecret().getBytes(StandardCharsets.UTF_8);
        Key signingKey = Keys.hmacShaKeyFor(keyBytes);
        
        // 使用应用的appSecret签名
        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(DateUtil.offset(new Date(), DateField.MONTH, 3))
                .signWith(signingKey, SignatureAlgorithm.HS512)  // 使用应用的appSecret和HS512算法
                .compact();
    }

    /**
     * 验证JWT Token并解析用户信息
     *
     * @param token JWT Token字符串
     * @return 用户认证信息
     */
    public ImUserAuthInfo validateToken(String token) {
        try {
            // 先解析token获取appId
            String appId = extractAppIdFromToken(token);

            // 获取应用信息
            ApplicationDto applicationDto = applicationService.getByAppId();
            if (applicationDto == null) {
                throw new ImBaseException(ImResultCode.USER_TOKEN_ERROR, StrUtil.format("appId:{}不存在", appId));
            }

            // 使用应用的appSecret验证token
            byte[] keyBytes = applicationDto.getAppSecret().getBytes(StandardCharsets.UTF_8);
            Key signingKey = Keys.hmacShaKeyFor(keyBytes);
            
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(signingKey)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();

            ImUserAuthInfo userAuthInfo = new ImUserAuthInfo();
            userAuthInfo.setAppId((String) claims.get("appId"));
            userAuthInfo.setUserId((String) claims.get("userId"));
            userAuthInfo.setUserType((String) claims.get("userType"));
            return userAuthInfo;
        } catch (io.jsonwebtoken.ExpiredJwtException e) {

            throw new ImBaseException(ImResultCode.USER_TOKEN_ERROR, StrUtil.format("Token已过期"));

        } catch (io.jsonwebtoken.security.SecurityException | io.jsonwebtoken.MalformedJwtException e) {

            throw new ImBaseException(ImResultCode.USER_TOKEN_ERROR, StrUtil.format("Token无效"));

        } catch (Exception e) {
            // Token验证失败
            throw new ImBaseException(ImResultCode.USER_TOKEN_ERROR, StrUtil.format("Token验证失败: {}", e.getMessage()));
        }
    }

    @Override
    public void validateSign(String sign) {

    }

    @Override
    public ImUserAuthInfo authUser(String token) {

        //TODO
        return ImUserAuthInfo.builder()
                .appId("appId")
                .userId(token)
                .userType("user")
                .expire(new Date())
                .build();
//        return validateToken(token);
    }

    /**
     * 从token中提取appId（不验证签名）
     */
    private String extractAppIdFromToken(String token) {
        try {
            String[] parts = token.split("\\.");
            if (parts.length != 3) {
                throw new ImBaseException(ImResultCode.USER_TOKEN_ERROR, "Token格式错误");
            }
            String payload = new String(Base64.getDecoder().decode(parts[1]));
            JSONObject jsonObject = JSON.parseObject(payload);
            return jsonObject.getString("appId");
        } catch (Exception e) {
            throw new ImBaseException(ImResultCode.USER_TOKEN_ERROR, "Token解析失败");
        }
    }
}
